package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.app.exception.BusinessExcepiton;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.face.AipFaceTemplate;
import com.itheima.autoconfig.huanxin.HuanXinTemplate;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.autoconfig.sms.SmsTemplate;
import com.itheima.domain.db.Freeze;
import com.itheima.domain.db.Log;
import com.itheima.domain.db.User;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.UserLike;
import com.itheima.service.db.FreezeService;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.db.UserService;
import com.itheima.service.mongo.UserLikeCountService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.JwtUtil;
import com.itheima.vo.*;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.*;

@Component //加入springmvc容器
public class UserManager {

    @DubboReference
    UserService userService;

    @Autowired
    SmsTemplate smsTemplate;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @DubboReference
    UserInfoService userInfoService;

    @Autowired
    AipFaceTemplate aipFaceTemplate;

    @Autowired
    OssTemplate ossTemplate;

    @Autowired
    HuanXinTemplate huanXinTemplate;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @DubboReference
    UserLikeCountService userLikeCountService;

    @DubboReference
    FreezeService freezeService;

    //保存用户
    public Long save(User user){
        Long id = userService.save(user);
        return id;
    }

    //根据手机查询用户
    public User findByMobile(String mobile){
        User user = userService.findByMobile(mobile, UserHolder.get().getId());
        return user;
    }

    //发送验证码
    public void sendCode(String phone) {
        //1.生成随机验证码
        String code = RandomUtil.randomNumbers(6);

        // TODO 以后项目上线了,删除
        code = "123456";

        //2.调用阿里云模板发送短信
        // TODO 以后项目上线了,开启注释
        //smsTemplate.sendSms(phone,code);

        //3.将验证码保存到redis中,时效5分钟  //  sms:13600136000 = 123456
        //stringRedisTemplate.opsForValue().set("sms:"+phone,code, Duration.ofMinutes(5));
        stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE+phone,code, Duration.ofMinutes(5));
    }

    //注册或登陆
    public ResponseEntity regAndLogin(Map<String, String> map) throws BusinessExcepiton {
        //1.获取用户提交过来的手机号和验证码
        String phone = map.get("phone");
        String verificationCode = map.get("verificationCode");

        //2.判断验证码是否和redis中的一致,若不一致,返回401
        String redisCode = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);

        //if(verificationCode != null && verificationCode.equals(redisCode)){}

        if (!StrUtil.equals(verificationCode,redisCode)) {
            //return ResponseEntity.status(500).body("你输入的验证码无效");
            return ResponseEntity.status(500).body(ErrorResult.codeError());
        }

        //3.通过手机号判断用户是否存在
        User user = userService.findByMobile(phone, null);
        Boolean isNew;
        if (user != null) {
            //3.1若存在,是老用户
            isNew = false;
            UserInfo userInfo = userInfoService.findByUserId(user.getId());
            String status = userInfo.getUserStatus();

            //判断是冻结
            if (!Objects.equals(status,"1")){
                Freeze freeze = freezeService.findByUserId(user.getId());
                //判断是否为冻结登录
                if (freeze.getFreezingRange() == 1){
                    throw new BusinessExcepiton("当前账号为冻结状态");
                }
            }
        }else {
            //3.2若不存在,是新用户,调用service完成保存操作
            isNew = true;

            //构造用户
            user = new User();
            user.setMobile(phone);
            user.setPassword(ConstantUtil.INIT_PASSWORD);
            Long id = userService.save(user);

            //别忘记将用户的id设置上去
            user.setId(id);

            //将用户也注册到环信上
            huanXinTemplate.register("HX"+id);
        }

        //4.生成token,(id和手机号)
        user.setPassword(null);//出去关键数据
        Map<String, Object> userMap = BeanUtil.beanToMap(user);
        String token = JwtUtil.createToken(userMap);

        //5.为了避免每次都解析token,将token作为key,用户的json数据做为value,放入redis中
        stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN+token, JSON.toJSONString(user),Duration.ofDays(30));

        //5.1 从redis中把验证码删除
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE+phone);

        //6.将token和是否新用户放入map中直接返回
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put("token",token);
        resultMap.put("isNew",isNew);

        //7.将用户的行为封装成日志对象,发送到mq中
        Log log = new Log();
        log.setUserId(user.getId());
        log.setLogTime(DateUtil.formatDate(new Date()));
        log.setPlace("广州天河黑马大楼");//固定地点
        log.setEquipment("华为P50");
        log.setType(isNew?"0102":"0101");

        //使用mq默认交换机
        rabbitTemplate.convertAndSend("tanhua.log",log);


        return ResponseEntity.ok(resultMap);
    }

    //完善用户信息
    public ResponseEntity saveUserInfo(UserInfo userInfo, String token) {
        /*//1.从token中获取用户
        User user = findUserFromToken(token);

        //1.1 判断用户是否为空,若为空,返回401
        if (user == null) {
            return ResponseEntity.status(401).body(null);
        }*/

        User user = UserHolder.get();

        //2.给userInfo设置用户id
        userInfo.setId(user.getId());
        //3.远程调用service完成保存操作
        userInfoService.save(userInfo);
        return ResponseEntity.ok(null);
    }

    public User findUserFromToken(String token) {
        if (StrUtil.isNotBlank(token)) {
            String userJson = stringRedisTemplate.opsForValue().get(ConstantUtil.USER_TOKEN + token);
            if (StrUtil.isNotBlank(userJson)) {
                return JSON.parseObject(userJson, User.class);
            }
        }
        return null;
    }

    // 更新用户头像
    public ResponseEntity saveUserInfoHead(String token, MultipartFile headPhoto) throws IOException {
        /*//1.从token中获取用户
        User user = findUserFromToken(token);

        //2.判断用户是否存在,若不存在返回401
        if (user == null) {
            return ResponseEntity.status(401).body(null);
        }*/

        User user = UserHolder.get();

        //3.调用百度云的人脸检测,若失败返回500
        if (!aipFaceTemplate.detect(headPhoto.getBytes())) {
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }

        //4.调用阿里云oss保存图片,返回url
        String url = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());

        //5.封装userInfo(设置id和头像)
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        //设置头像
        userInfo.setAvatar(url);
        //设置封面
        userInfo.setCoverPic(url);

        //6.远程调用service完成更新
        userInfoService.update(userInfo);
        return ResponseEntity.ok(null);
    }

    //查询用户信息
    public ResponseEntity findUserInfoById(Long userID) {
        //1.远程调用service完成查询,返回UserInfo
        UserInfo userInfo = userInfoService.findByUserId(userID);

        //2.新建UserInfoVo
        UserInfoVo vo = new UserInfoVo();

        //3.将userInfo中的数据拷贝给vo(使用spring提供的工具类)
        //参数1:原来有数据的对象
        //参数2:目标对象
        BeanUtils.copyProperties(userInfo,vo);

        //4.返回vo
        return ResponseEntity.ok(vo);
    }

    //修改用户信息
    public ResponseEntity updateUserInfo(String token, UserInfo userInfo) {
        /*//1.从token中获取用户
        User user = findUserFromToken(token);

        //2.判断用户是否存在,若不存在返回401
        if (user == null) {
            return ResponseEntity.status(401).body(null);
        }*/

        User user = UserHolder.get();

        //3.给userInfo设置id
        userInfo.setId(user.getId());

        //4.远程调用service完成更新
        userInfoService.update(userInfo);
        return ResponseEntity.ok(null);
    }


    //统计 互相喜欢，喜欢，粉丝数量
    public ResponseEntity selectUserLikeCount() {
        //调用UserHandler查询用户id
        Long userId = UserHolder.get().getId();

        //根据用户的id调用远程service，获取
        UserLikeCountVo vo = userLikeCountService.selectCount(userId);

        //返回vo类型
        return ResponseEntity.ok(vo);
    }

    //互相喜欢、喜欢、粉丝、谁看过我 - 翻页列表
    public ResponseEntity selectFriends(Integer pageNum, Integer pageSize, Integer type) {
        //调用UserHandler查询用户id
        Long userId = UserHolder.get().getId();
        //根据用户的id调用远程service，获取
        PageBeanVo pageBeanVo = userLikeCountService.selectPageByType(type,userId,pageNum,pageSize);

        //根据pageBeanVo，获取分页数据，转成UserLike类型
        List<Long> items = (List<Long>) pageBeanVo.getItems();

        //初始化UserLike集合
        List<UserLikeVo> vos = new ArrayList<>();

        //判断分页数据是否为空
        if (CollectionUtil.isNotEmpty(items)) {
            //不为空的话，遍历集合，拿到每一个UserLike之后获取likeUserId，根据这个字段，查询UseInfo,并加入userINfgo集合中
            items.forEach(e -> {
                UserInfo userInfo = userInfoService.findByUserId(e);
                UserLikeVo vo = new UserLikeVo();
                BeanUtils.copyProperties(userInfo, vo);
                vos.add(vo);
            });

        }


        //重新封装pageBeanVo
        pageBeanVo.setItems(vos);

        //返回数据
        return ResponseEntity.ok(pageBeanVo);


    }

    public void like(Integer uid) {
        //调用UserHandler查询用户id
        Long userId = UserHolder.get().getId();

        userLikeCountService.like(userId, uid);
    }

    public void noLike(Integer uid) {
        //调用UserHandler查询用户id
        Long userId = UserHolder.get().getId();

        userLikeCountService.noLike(userId, uid);

    }
}
